#ifndef SLAB_ALLOC_H
#define SLAB_ALLOC_H

#include <List.h>
#include <Types.h>
#include <BuddyAllocator.h>

#define PGSIZE	4096
#define PGMASK	0xFFFFF000

class Slab{
	public:
	uint32			objSize;		//Размер объекта
	uint32			objCount;		//Счетчик используемых объектов
	uint32			objNum;			//Количество объектов в участке
	List			objList;		//Список свободных объектов в участке
	Link			slabs;			//Указатели списка участков
	Frame			*fpage;			//Если != NULL, то содержит указатель на первую страницу участка
	uint16			d;
	public:
	Slab(uint32 sz);
	
	inline uint32 getObjSize(){
		return objSize;
	}	
	/*Операция выделения памяти для самого объекта Slab, см. SlabAllocator.cc*/
	void * operator new(size_t, uint32 pr);
	/*Метод для выделения памяти под объект в участке*/
	void * s_malloc(size_t);
	/*Метод для освобождения памяти объекта*/
	void s_mfree(void *addr);
	/*Проверка участка на полноту*/
	inline uint32 isFull(){
		if(objCount == objNum) return 1; 
		else return 0;
	}
};



class SlabAllocator{
	uint32	objSize;		//Размер объекта используемого в области
	List	freeSlabs;		//Свободные участки
	List	notFreeSlabs;	//Не свободные участи
	List	fullSlabs;		//Занятые участки
	private:
		/*Выделение нового участка*/
		inline Slab * allocSlab(){
			if(objSize > 512) return new(1) Slab(objSize);
			return new(2) Slab(objSize);
		}
	public:
		SlabAllocator(){}
		SlabAllocator(size_t sz);
		inline void init(size_t sz){
			objSize = sz;
		}
		inline uint32 getObjSize(){
			return objSize;
		}
		void * sa_malloc();
		void sa_mfree(void *obj);
		void * operator new(size_t sz, void *addr);
};

extern SlabAllocator *privateAllocator;
extern SlabAllocator prvSlbAlloc;

#define MIN_ORDER	5
#define MAX_ORDER	11
#define COMMON_ALLOCS_NR MAX_ORDER - MIN_ORDER + 1

class CommonAllocator{
	SlabAllocator	slabAllocs[COMMON_ALLOCS_NR];
	public:
		CommonAllocator();
		
		void * ca_malloc(size_t sz);
		void ca_mfree(void *obj);
		void * operator new(size_t sz, void *addr);
};

extern CommonAllocator *commonAllocator;

void * operator new(size_t sz, SlabAllocator *sa);

void * operator new(size_t sz, SlabAllocator &sa);

void * operator new(size_t sz);

template<class X> void destroy(X* p, SlabAllocator *sa);

void operator delete(void *obj);

#endif /* SLAB_ALLOC_H */

